package com.tourism.core.cn.utils;
/*********************************************************************
 Copyright(c) 2025 All Rights Reserved .
 Author : liliang
 CreatedOn : 2025/1/2 20:09
 Email : 2061996582@qq.com
 Describe : 提供了完整的 token 生命周期管理,生成 、验证 、解析 、刷新
 UseCase :
 Version : 2025|V1.0.0.0
 **********************************************************************/

import com.tourism.core.cn.config.JwtConfig;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author new
 * @date 2025/1/2 20:09
 * 用户登录成功后，生成包含用户信息的 token
 * 在后续请求中，验证 token 的有效性
 * 从 token 中解析出用户信息
 * 支持 token 的刷新
 */
@Slf4j
@Component
public class JwtUtil {
    private final JwtConfig jwtConfig;

    public JwtUtil(JwtConfig jwtConfig) {
        this.jwtConfig = jwtConfig;
    }

    private SecretKey getSecretKey() {
        return Keys.hmacShaKeyFor(jwtConfig.getSecret().getBytes());
    }

    /**
     * 生成token
     * @param userId 用户ID
     * @param username 用户名
     * @return token字符串
     */
    public String generateToken(Long userId, String username) {
        Map<String, Object> claims = new HashMap<>();

        claims.put("userId", userId);
        claims.put("username", username);
        return generateToken(claims);
    }

    /**
     * 从token中获取用户ID
     * @param token token字符串
     * @return 用户ID
     */
    public Long getUserIdFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        return claims.get("userId", Long.class);
    }

    /**
     * 从token中获取用户名
     * @param token token字符串
     * @return 用户名
     */
    public String getUsernameFromToken(String token) {
        Claims claims = getClaimsFromToken(token);
        return claims.get("username", String.class);
    }

    /**
     * 验证token是否有效
     * @param token token字符串
     * @return 是否有效
     */
    public boolean validateToken(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(getSecretKey())
                    .build()
                    .parseClaimsJws(token);// 尝试解析token
            return true; // 解析成功则有效
        }catch (Exception e){
            log.error("Invalid JWT token: {}", e.getMessage());
            return false; // 解析失败
        }
    }

    /**
     * 判断token是否过期
     * @param token token字符串
     * @return 是否过期
     */
    public boolean isTokenExpired(String token) {
        Claims claimsFromToken = getClaimsFromToken(token);
        return claimsFromToken.getExpiration().before(new Date());// 传入当前时间，比较过期时间
    }

    /**
     * 刷新token
     * @param token 原token
     * @return 新token
     */
    public String refreshToken(String token) {
        Claims claimsFromToken = getClaimsFromToken(token);
        return generateToken(claimsFromToken);
    }


    // 私有的生成token方法
    private String generateToken(Map<String, Object> claims) {
        Date createdDate = new Date();
        // 设置过期时间
        Date expirationDate = new Date(createdDate.getTime() + jwtConfig.getExpiration() * 1000);

        //生成token
        return Jwts.builder()
                .setClaims(claims)//设置载荷
                .setIssuedAt(createdDate)//设置创建时间
                .setExpiration(expirationDate)//设置过期时间
                .signWith(getSecretKey(), SignatureAlgorithm.HS256)//设置使用HS256签名算法
                .compact(); // 生成最终的token字符串
    }

    // 私有的解析token方法
    private Claims getClaimsFromToken(String token){
        return Jwts.parserBuilder()
                .setSigningKey(getSecretKey())// 设置密钥
                .build()
                .parseClaimsJws(token)// 解析token
                .getBody();// 获取数据部分
    }

}
